package com.lix.langrensha.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.lix.langrensha.contants.CommonStatusCode;
import com.lix.langrensha.contants.ProcessConstant;
import com.lix.langrensha.contants.RoleConstant;
import com.lix.langrensha.contants.SkillConstant;
import com.lix.langrensha.model.*;
import com.lix.langrensha.utils.MyWebSocket;
import com.lix.langrensha.utils.RtnJson;
import com.lix.langrensha.utils.WxAppUtil;
import com.sun.xml.internal.bind.v2.TODO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author lix
 * @create 2019/12/11-10:20
 * @description
 */
@Service
@Slf4j
public class LangRenShaService {
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private CreateRoleService createRoleService;


    /**
     * 创建房间
     *
     * @param homeownerId
     * @param roleJson
     * @return
     */
    public Room createRoom(String homeownerId, String roleJson) {
        JSONArray objects = JSONObject.parseArray(roleJson);
        List<Integer> roles = objects.toJavaList(Integer.class);
        Room room = new Room();
        room.setHomeownerId(homeownerId);
        int roomId = (int) ((Math.random() * 9 + 1) * 100000);
        log.error("===========房间号===========" + roomId);
        room.setRoomId(roomId);
        ArrayList<User> users = new ArrayList<>();
        LinkedList<Integer> seats = new LinkedList<>();
        while (seats.size() < roles.size()) {
            int i = (int) (Math.random() * roles.size() + 1);
            if (!seats.contains(i))
                seats.add(i);
        }
        for (int i = 0; i < roles.size(); i++) {
            User user = new User();
            user.setSeatNum(seats.get(i));
            switch (roles.get(i)) {
                case 1:
                    createRoleService.createPingMin(user);
                    room.setGoodPersonNum(room.getGoodPersonNum() + 1);
                    break;
                case 2:
                    createRoleService.createLangRen(user);
                    room.setLangRenNum(room.getLangRenNum() + 1);
                    break;
                case 3:
                    createRoleService.createNvWu(user);
                    room.setGoodPersonNum(room.getGoodPersonNum() + 1);
                    room.setNvWuNum(room.getNvWuNum() + 1);
                    break;
                case 4:
                    createRoleService.createYuYanJia(user);
                    room.setGoodPersonNum(room.getGoodPersonNum() + 1);
                    room.setYuYanJiaNum(room.getYuYanJiaNum() + 1);
                    break;
                case 5:
                    createRoleService.createShouWei(user);
                    room.setGoodPersonNum(room.getGoodPersonNum() + 1);
                    room.setShouWeiNum(room.getShouWeiNum() + 1);
                    room.setShouWeiFlag(true);
                    break;
                case 6:
                    createRoleService.createLieRen(user);
                    room.setGoodPersonNum(room.getGoodPersonNum() + 1);
                    room.setLieRenNum(room.getLieRenNum() + 1);
                    break;
                case 7:
                    createRoleService.createZhaDanRen(user);
                    room.setGoodPersonNum(room.getGoodPersonNum() + 1);
                    room.setZhaDanRenNum(room.getZhaDanRenNum() + 1);
                    break;
                case 8:
                    createRoleService.createYinLang(user);
                    room.setYinLangNum(room.getYinLangNum() + 1);
                    break;
                case 9:
                    createRoleService.createBaiChi(user);
                    room.setGoodPersonNum(room.getGoodPersonNum() + 1);
                    break;
                case 10:
                    createRoleService.createXiong(user);
                    room.setGoodPersonNum(room.getGoodPersonNum() + 1);
                    room.setXiongNum(room.getXiongNum() + 1);
                    room.setXiongFlag(true);
                    break;
                default:
            }
            users.add(user);
        }
        List<User> collect = users.stream().sorted(Comparator.comparing(User::getSeatNum)).collect(Collectors.toList());
        room.setUsers(collect);
        room.setRoomSeatNum(users.size());
        redisTemplate.opsForValue().set(roomId + "init", room);
        redisTemplate.opsForValue().set(roomId, room);
        try {
            MyWebSocket.sendInfo("1");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return room;
    }

    /**
     * 获取微信用户信息
     *
     * @param code
     * @return
     */
    public JSONObject getWxUserInfo(String code) throws IOException {
        String url = "https://api.weixin.qq.com/sns/jscode2session?appid=wx2b5aacf5da4936da&secret=85049b09829ec570fa8851df2a027514&js_code=" + code + "&grant_type=authorization_code";
        JSONObject jsonObject = WxAppUtil.doGetStr(url);
        return jsonObject;
    }


    /**
     * 查看房间状态
     *
     * @param roomId
     * @return
     */
    public Room roomInfo(int roomId) {
        return (Room) redisTemplate.opsForValue().get(roomId);
    }

    /**
     * 更新房间状态
     *
     * @param room
     * @return
     */
    public Room updateRoomStatus(Room room) {
        redisTemplate.opsForValue().set(room.getRoomId(), room);
        try {
            MyWebSocket.sendInfo("1");
        } catch (IOException e) {
            log.error(e.getMessage());
        }
        return (Room) redisTemplate.opsForValue().get(room.getRoomId());
    }


    /**
     * 入座
     *
     * @param roomId
     * @param username
     * @param userId
     * @param avatarUrl
     * @param seatNum
     * @return
     */
    public RtnJson Seating(int roomId, String username, String userId, String avatarUrl, int seatNum) {
        Room room = roomInfo(roomId);
        for (User value : room.getUsers()) {
            if (null != value.getUserId()) {
                if (value.getUserId().equals(userId)) {
                    return RtnJson.toFail(CommonStatusCode.E00010005);
                } else if (value.getSeatNum() == seatNum) {
                    return RtnJson.toFail(CommonStatusCode.E00010004);
                }
            }
        }
        List<User> users = room.getUsers();
        for (User user : users) {
            if (seatNum == user.getSeatNum() && null == user.getUserId()) {
                user.setUsername(username);
                user.setAvatarUrl(avatarUrl);
                user.setUserId(userId);
                room.setRoomSeatNum(room.getRoomSeatNum() - 1);
                room.setRoomStatus(1);
                updateRoomStatus(room);
                return RtnJson.toSuccess(user);
            }
        }
        return RtnJson.toFail(CommonStatusCode.E00010004);
    }

    /**
     * 查询user信息
     *
     * @param roomId
     * @param userId
     * @return
     */
    public User userInfo(int roomId, String userId) {
        Room room = roomInfo(roomId);
        for (User user : room.getUsers()) {
            if (null != user.getUserId() && user.getUserId().equals(userId)) {
                return user;
            }
        }
        try {
            MyWebSocket.sendInfo("1");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 开始游戏
     *
     * @param roomId
     * @param homeownerId
     * @param roomStatus
     * @return
     */
    public RtnJson night(int roomId, String homeownerId) {
        log.error(roomId + "进入黑夜");
        Room room = roomInfo(roomId);
        if (!room.getHomeownerId().equals(homeownerId)) {
            return RtnJson.toFail(CommonStatusCode.E00010006);
        }
        if (room.getRoomSeatNum() > 0) {
            return RtnJson.toFail(CommonStatusCode.E00010002);
        }

        room.setRoomStatus(2);
        updateRoomStatus(room);
        return RtnJson.toSuccess(CommonStatusCode.S00000000);
    }


    /**
     * 删除房间
     *
     * @param roomId
     */
    public void deleteRoom(int roomId) {
        Room room = roomInfo(roomId);
        for (User user : room.getUsers()) {
            redisTemplate.delete(user.getUserId());
        }
        redisTemplate.delete(roomId);
    }

    /**
     * 重新发牌
     *
     * @param roomId
     * @param homeownerId
     * @return
     */
    public RtnJson shuffle(int roomId, String homeownerId) {
        Room initRoom = (Room) redisTemplate.opsForValue().get(roomId + "init");
        Room room = roomInfo(roomId);
        room.setLieRenNum(initRoom.getLieRenNum());
        room.setZhaDanRenNum(initRoom.getZhaDanRenNum());
        room.setGoodPersonNum(initRoom.getGoodPersonNum());
        room.setWinner(initRoom.getWinner());
        room.setYinLangNum(initRoom.getYinLangNum());
        room.setLangRenNum(initRoom.getLangRenNum());
        room.setShouWeiFlag(initRoom.isShouWeiFlag());
        room.setShouWeiNum(initRoom.getShouWeiNum());
        room.setYuYanJiaNum(initRoom.getYuYanJiaNum());
        room.setNvWuNum(initRoom.getNvWuNum());
        room.setXiongNum(initRoom.getXiongNum());
        room.setRoomSeatNum(initRoom.getRoomSeatNum());
        room.setRoomStatus(1);
        room.setVoteMap(new ArrayList<>());
//        清楚缓存
        cleanValueCahe(roomId, "shouWei");
        cleanValueCahe(roomId, "dead");
        cleanVoteCache(roomId, "langRen");
        if (!room.getHomeownerId().equals(homeownerId)) {
            return RtnJson.toFail(CommonStatusCode.E00010006);
        }
        List<User> users = initRoom.getUsers();
        List<RolePojo> roles = users.stream().map(User::getRole).collect(Collectors.toList());
        ArrayList<Integer> seats = new ArrayList<>();
        while (seats.size() < roles.size()) {
            int i = (int) (Math.random() * roles.size());
            if (!seats.contains(i))
                seats.add(i);
        }
//        加个已经选完的集合,完成尽可能完全随机
        ArrayList<Object> already = new ArrayList<>(seats.size());
        for (int i = 0; i < users.size(); i++) {
            log.info(i + "号更换职业之前是:" + users.get(i).getRole().getRoleName());
            for (Integer seat : seats) {
                RolePojo rolePojo = roles.get(seat);
                if (users.get(i).getRole().getRoleId() != rolePojo.getRoleId() && !already.contains(seat)) {
                    users.get(i).setRole(rolePojo);
                    already.add(seat);
                    break;
                }
            }
//            复活
            users.get(i).setHp(1);
//            技能装填
            for (SkillPojo skillPojo : users.get(i).getRole().getSkill()) {
                skillPojo.setNum(1);
            }
            log.info(i + "号更换职业之后是:" + users.get(i).getRole().getRoleName());
        }
        room.setUsers(users);
        updateRoomStatus(room);
        RtnJson<Object> rtnJson = new RtnJson<>();
        rtnJson.setData(room);
        rtnJson.setStatus(CommonStatusCode.S00010002.getCode());
        rtnJson.setMessage(CommonStatusCode.S00010002.getMessage());
        return rtnJson;
    }

    /**
     * 设置座位死亡(房主设置)
     *
     * @param roomId
     * @param homeownerId
     * @param seatNum
     * @return
     */
    public Room setDead(Room room, int seatNum) {
        List<User> users = room.getUsers();
        for (User user : users) {
            if (user.getSeatNum() == seatNum) {
                user.setHp(0);
                log.error("死亡的是:" + seatNum + "号");
                switch (user.getRole().getRoleId()) {
                    case 2:
                        room.setLangRenNum(room.getLangRenNum() == 0 ? 0 : room.getLangRenNum() - 1);
                        break;
                    case 3:
                        room.setNvWuNum(room.getNvWuNum() == 0 ? 0 : room.getNvWuNum() - 1);
                        room.setGoodPersonNum(room.getGoodPersonNum() == 0 ? 0 : room.getGoodPersonNum() - 1);
                        break;
                    case 4:
                        room.setYuYanJiaNum(room.getYuYanJiaNum() == 0 ? 0 : room.getYuYanJiaNum() - 1);
                        room.setGoodPersonNum(room.getGoodPersonNum() == 0 ? 0 : room.getGoodPersonNum() - 1);
                        break;
                    case 5:
                        room.setShouWeiNum(room.getShouWeiNum() == 0 ? 0 : room.getShouWeiNum() - 1);
                        room.setGoodPersonNum(room.getGoodPersonNum() == 0 ? 0 : room.getGoodPersonNum() - 1);
                        break;
                    case 6:
                        room.setLieRenNum(room.getLieRenNum() == 0 ? 0 : room.getLieRenNum() - 1);
                        room.setGoodPersonNum(room.getGoodPersonNum() == 0 ? 0 : room.getGoodPersonNum() - 1);
                        room.setRoomStatus(ProcessConstant.LIE_REN.getStatus());
                        break;
                    case 7:
                        room.setZhaDanRenNum(room.getZhaDanRenNum() == 0 ? 0 : room.getZhaDanRenNum() - 1);
                        room.setGoodPersonNum(room.getGoodPersonNum() == 0 ? 0 : room.getGoodPersonNum() - 1);
                        break;
                    case 8:
                        room.setYinLangNum(room.getYinLangNum() == 0 ? 0 : room.getYinLangNum() - 1);
                        break;
                    case 10:
                        room.setXiongNum(room.getXiongNum() == 0 ? 0 : room.getXiongNum() - 1);
                        room.setGoodPersonNum(room.getGoodPersonNum() == 0 ? 0 : room.getGoodPersonNum() - 1);
                        break;
                    default:
                }
                room = updateRoomStatus(room);
            }
        }
//        结算
        room = Settlement(room);
        return room;
    }

    /**
     * 结算(胜/负)
     *
     * @param room
     * @return
     */
    private Room Settlement(Room room) {
//        激活隐狼
        if (room.getLangRenNum() == 0 && room.getYinLangNum() != 0) {
            room.setYinLangFlag(true);
            for (User user : room.getUsers()) {
                if (user.getRole().getRoleId() == 8) {
                    RolePojo langRen = new RolePojo();
                    ArrayList<SkillPojo> skillPojos = new ArrayList<>(2);
                    SkillPojo skillPojo = new SkillPojo();
                    langRen.setRoleId(RoleConstant.LANG_REN.getRoleId());
                    langRen.setRoleName(RoleConstant.LANG_REN.getRoleName());
                    skillPojo.setSkillId(SkillConstant.SHA.getSkillId());
                    skillPojo.setSkillName(SkillConstant.SHA.getSkillName());
                    skillPojo.setNum(1);
                    skillPojos.add(skillPojo);
                    langRen.setSkill(skillPojos);
                    user.setRole(langRen);
                    room.setLangRenNum(1);
                    updateRoomStatus(room);
                }
            }
        }
        if (room.isYinLangFlag()) {
            if (room.getYinLangNum() == 0) {
                room.setWinner(1);
                return updateRoomStatus(room);
            }
        } else {
            if (room.getLangRenNum() == 0) {
                room.setWinner(1);
                return updateRoomStatus(room);
            }
        }

        if (room.getShouWeiNum() <= 0 && room.getLieRenNum() <= 0 && room.getZhaDanRenNum() <= 0) {
            if (room.getLangRenNum() + room.getYinLangNum() >= room.getGoodPersonNum()) {
                room.setWinner(2);
            }
        }
        return updateRoomStatus(room);
    }

    /**
     * 设置 开始/结束 投票
     *
     * @param roomId
     * @param homeownerId
     * @return
     */
    public RtnJson startVote(int roomId, String homeownerId, boolean flag) {
        Room room = roomInfo(roomId);
        if (!room.getHomeownerId().equals(homeownerId)) {
            return RtnJson.toFail(CommonStatusCode.E00010006);
        }
        if (flag) {
            room.setRoomStatus(ProcessConstant.TOU_PIAO.getStatus());
            ArrayList<String> voteMap = new ArrayList<>();
            cleanVoteCache(room.getRoomId(), "vote");
            room.setVoteMap(voteMap);
        } else {
            List<String> voteMap = room.getVoteMap();
            HashMap<Integer, String> map = new HashMap<>();
            Map voteCache = getVoteCache(roomId, "vote");
            if (!CollectionUtils.isEmpty(voteCache)) {
//               设置投票结果
                Set<Integer> keys = voteCache.keySet();
                for (Integer key : keys) {
                    Integer value = (Integer) voteCache.get(key);
                    String s = (String) map.get(value);
                    if (StringUtils.isEmpty(s)) {
                        s = " ";
                    }
                    map.put(value, s += key + ",");
                }
                for (Integer integer : map.keySet()) {
                    voteMap.add(map.get(integer) + "---->" + integer);
                }
                log.error("投票详情:" + room.getVoteMap().toString());
                //投票的人数进行统计(并设置死亡)
                LinkedHashMap<Integer, Integer> sortMap = countVote(roomId, voteCache);
                int first = 0;
                int second = 0;
                int dead = 0;
                int num = 0;
                for (Map.Entry<Integer, Integer> entry : sortMap.entrySet()) {
                    if (num == 0) {
                        first = entry.getValue();
                        dead = entry.getKey();
                    } else if (num == 1) {
                        second = entry.getValue();
                    }
                    num++;
                }
                room.setRoomStatus(ProcessConstant.CHU_JUE.getStatus());
                updateRoomStatus(room);
                sleepTime(2000);
                if (first != 0 && first != second) {
                    for (User user : room.getUsers()) {
                        if (user.getSeatNum() == dead) {
                            if (user.getRole().getRoleId() == 9) {
                                room.setRoomStatus(ProcessConstant.BAI_CHI.getStatus());
                                updateRoomStatus(room);
                                return RtnJson.toSuccess();
                            }
                        }
                    }
                    room = setDead(room, dead);
                    log.error("处决的是:" + dead);
                    for (User user : room.getUsers()) {
                        if (user.getSeatNum() == dead) {
                            if (user.getRole().getRoleId() == 7) {
                                String[] split = map.get(dead).split(",");
                                room.setRoomStatus(ProcessConstant.ZHA_DAN_REN.getStatus());
                                updateRoomStatus(room);
                                sleepTime(2000);
                                for (String s : split) {
                                    room = setDead(room, Integer.valueOf(s.trim()));
                                }
                                return RtnJson.toSuccess();
                            }
                        }
                    }
                }
            } else {
                room.setRoomStatus(ProcessConstant.CHU_JUE.getStatus());
            }
        }
        updateRoomStatus(room);
        return RtnJson.toSuccess();
    }

    /**
     * 统计投票
     *
     * @param roomId
     * @param voteCache
     * @return
     */
    private LinkedHashMap<Integer, Integer> countVote(int roomId, Map voteCache) {
        HashMap<Integer, Integer> dead = new HashMap<>();
        for (Object value : voteCache.values()) {
            Integer targetInt = dead.get(value);
            if (null == targetInt) {
                dead.put((Integer) value, 1);
            } else {
                dead.put((Integer) value, targetInt + 1);
            }
        }
        LinkedHashMap<Integer, Integer> linkedHashMap = new LinkedHashMap<>();
        dead.entrySet().stream().sorted(Map.Entry.<Integer, Integer>comparingByValue()
                .reversed())
                .forEachOrdered(e -> {
                    linkedHashMap.put(e.getKey(), e.getValue());
                });
        log.error("投票排序:" + linkedHashMap.toString());
        return linkedHashMap;
    }

    /**
     * 清空投票缓存
     *
     * @param roomId
     */
    private void cleanVoteCache(int roomId, String status) {
        redisTemplate.delete(roomId + status);
    }

    /**
     * 投票
     *
     * @param roomId
     * @param seatNum
     * @param target
     * @return
     * @
     */
    public RtnJson vote(int roomId, int seatNum, int target) {
        Room room = roomInfo(roomId);
        if (room.getRoomStatus() != ProcessConstant.TOU_PIAO.getStatus()) {
            return RtnJson.toFail(CommonStatusCode.E00010008);
        }
        setVoteCache(roomId, "vote", seatNum, target);
        return RtnJson.toSuccess();
    }

    /**
     * 获取map缓存
     *
     * @param roomId
     * @param status
     * @return
     */
    private Map getVoteCache(int roomId, String status) {
        return redisTemplate.opsForHash().entries(roomId + status);
    }

    /**
     * 设置map缓存
     *
     * @param roomId
     * @param status
     * @param seatNum
     * @param target
     */
    private void setVoteCache(int roomId, String status, int seatNum, int target) {
        redisTemplate.opsForHash().put(roomId + status, seatNum, target);
    }


    /**
     * 个角色使用技能
     *
     * @param userId
     * @param id
     * @param roomId
     * @param target
     * @param roleId
     * @return
     */
    public RtnJson useSkill(int roomId, int effect, int seatNum, int target, int roleId) {
        Room room = roomInfo(roomId);
        switch (roleId) {
            case 2:
                return langRenSkill(roomId, seatNum, target, room);
            case 3:
                return nvWuSkill(roomId, effect, seatNum, target, room);
            case 4:
                return yuYanJiaSkill(roomId, seatNum, target, room);
            case 5:
                return shouWeiSkill(roomId, seatNum, target, room);
            case 6:
                return lieRenSkill(roomId, seatNum, target, room);
//            case 7:
//                return zhaDanRenSkill(roomId, seatNum, target, room);
            default:
        }
        return RtnJson.toFail(CommonStatusCode.E00010009);
    }

    /**
     * 猎人技能
     *
     * @param roomId
     * @param seatNum
     * @param target
     * @param room
     * @return
     */
    private RtnJson lieRenSkill(int roomId, int seatNum, int target, Room room) {
        if (room.getRoomStatus() != ProcessConstant.LIE_REN.getStatus()) {
            return RtnJson.toFail(CommonStatusCode.E00010009);
        }
        if (target == 0) {
            return RtnJson.toFail(CommonStatusCode.E00010011);
        }
        for (User user : room.getUsers()) {
            if (user.getRole().getRoleId() == 6 && user.getSeatNum() == seatNum) {
                if (user.getRole().getSkill().get(0).getNum() == 0) {
                    return RtnJson.toFail(CommonStatusCode.E00010012);
                }
                user.getRole().getSkill().get(0).setNum(0);
                room = setDead(room, target);
            }
        }
        return RtnJson.toSuccess(room);
    }

    /**
     * 守卫守护
     *
     * @param roomId
     * @param seatNum
     * @param target
     * @param room
     * @return
     */
    private RtnJson shouWeiSkill(int roomId, int seatNum, int target, Room room) {
        if (room.getRoomStatus() != ProcessConstant.SHOU_WEI_ZHENG_YAN.getStatus()) {
            return RtnJson.toFail(CommonStatusCode.E00010009);
        }
        if (target != 0) {
            int shouWei = getValueCache(roomId, "shouWei");
            if (shouWei == target) {
                return RtnJson.toFail(CommonStatusCode.E00010010);
            }
            setValueCache(roomId, "shouWei", target);
            log.error("守卫守护的是:" + target);
        }
        room.setRoomStatus(ProcessConstant.SHOU_WEI_BI_YAN.getStatus());
        updateRoomStatus(room);
        sleepTime(2000);
        room.setRoomStatus(ProcessConstant.YU_YAN_JIA_ZHENG_YAN.getStatus());
        updateRoomStatus(room);
        if (room.getYuYanJiaNum() == 0) {
            sleepTime((int) (Math.random() * 5 + 8) * 1000);
            room.setRoomStatus(ProcessConstant.YU_YAN_JIA_BI_YAN.getStatus());
            updateRoomStatus(room);
            sleepTime(2000);
            room.setRoomStatus(ProcessConstant.NV_WU_ZHENG_YAN.getStatus());
            room = updateRoomStatus(room);
            if (room.getNvWuNum() == 0) {
                sleepTime((int) (Math.random() * 5 + 8) * 1000);
                ArrayList<Integer> deadList = new ArrayList<>();
                int shouWei = getValueCache(roomId, "shouWei");
                int langRenTarg = getValueCache(roomId, "dead");
                if (langRenTarg != 0) {
                    if (langRenTarg != shouWei) {
                        room = setDead(room, langRenTarg);
                        deadList.add(langRenTarg);
                    }
                }
                return setDawnStatus(roomId, room, deadList);
            }
        }
        return RtnJson.toSuccess();
    }

    /**
     * 预言家技能
     *
     * @param roomId
     * @param seatNum
     * @param target
     * @param room
     * @return
     */
    private RtnJson yuYanJiaSkill(int roomId, int seatNum, int target, Room room) {
        if (room.getRoomStatus() != ProcessConstant.YU_YAN_JIA_ZHENG_YAN.getStatus()) {
            return RtnJson.toFail(CommonStatusCode.E00010009);
        }
        room.setRoomStatus(ProcessConstant.YU_YAN_JIA_BI_YAN.getStatus());
        room = updateRoomStatus(room);
        sleepTime(2000);
        room.setRoomStatus(ProcessConstant.NV_WU_ZHENG_YAN.getStatus());
        room = updateRoomStatus(room);
        if (room.getNvWuNum() == 0) {
            sleepTime((int) (Math.random() * 5 + 8) * 1000);
            room.setRoomStatus(ProcessConstant.NV_WU_BI_YAN.getStatus());
            room = updateRoomStatus(room);
            sleepTime(2000);
            ArrayList<Integer> deadList = new ArrayList<>();
            int shouWei = getValueCache(roomId, "shouWei");
            int langRenTarg = getValueCache(roomId, "dead");
            if (langRenTarg != 0) {
                if (langRenTarg != shouWei) {
                    room = setDead(room, langRenTarg);
                    deadList.add(langRenTarg);
                }
            }
            return setDawnStatus(roomId, room, deadList);
        }
        return RtnJson.toSuccess();
    }

    /**
     * 女巫使用技能
     *
     * @param id
     * @param roomId
     * @param seatNum
     * @param target
     * @param room
     * @return
     */
    private RtnJson nvWuSkill(int roomId, int effect, int seatNum, int target, Room room) {
        if (room.getRoomStatus() != ProcessConstant.NV_WU_ZHENG_YAN.getStatus()) {
            return RtnJson.toFail(CommonStatusCode.E00010009);
        }
        int shouWei = 0;
        if (room.isShouWeiFlag()) {
            shouWei = getValueCache(roomId, "shouWei");
        }
        int langRen = getValueCache(roomId, "dead");

        ArrayList<Integer> deadList = new ArrayList<>();
        if (target != 0) {
            for (User user : room.getUsers()) {
                if (user.getSeatNum() == seatNum) {
                    if (effect == 1) {
                        //解药
                        if (shouWei == target) {
                            room = setDead(room, target);
                            deadList.add(target);
                        }
                        log.error("女巫使用解药目标是---->" + target + "号");
                        user.getRole().getSkill().get(0).setNum(0);
                        updateRoomStatus(room);
                    } else {
                        //毒药
                        if (shouWei != target) {
                            room = setDead(room, target);
                            deadList.add(target);
                            log.error("女巫使用毒药目标是---->" + target + "号");
                        }
                        if (langRen != shouWei) {
                            room = setDead(room, langRen);
                            deadList.add(langRen);
                            log.error("狼人杀的目标是---->" + langRen + "号");
                        }
                        user.getRole().getSkill().get(1).setNum(0);
                        room = updateRoomStatus(room);
                    }
                }
            }
        } else if (target == 0) {
//            不使用
            log.error("女巫不使用技能");
            if (langRen != 0) {
                if (langRen != shouWei) {
                    room = setDead(room, langRen);
                    deadList.add(langRen);
                }
            }
        }
        room.setRoomStatus(ProcessConstant.NV_WU_BI_YAN.getStatus());
        room = updateRoomStatus(room);
        sleepTime(1000);
        return setDawnStatus(roomId, room, deadList);
    }

    private RtnJson setDawnStatus(int roomId, Room room, ArrayList<Integer> deadList) {
        if (deadList.size() != 0) {
            room.setRoomStatus(ProcessConstant.TIAN_LIANG.getStatus());
            room = updateRoomStatus(room);
            int lieRenSeatNum = 0;
            for (User user : room.getUsers()) {
                if (user.getRole().getRoleId() == 6) {
                    lieRenSeatNum = user.getSeatNum();
                }
            }
            sleepTime(3500);
//            熊咆哮判断
            if (room.isXiongFlag()) {
                room = roar(room);
            }
            if (deadList.contains(lieRenSeatNum)) {
                sleepTime(3000);
                room.setRoomStatus(ProcessConstant.LIE_REN.getStatus());
                room = updateRoomStatus(room);
            }
            cleanValueCahe(roomId, "dead");
            return RtnJson.toSuccess();
        } else {
            room.setRoomStatus(ProcessConstant.PING_AN_YE.getStatus());
            room = updateRoomStatus(room);
            sleepTime(3500);
//            熊咆哮判断
            if (room.isXiongFlag()) {
                room = roar(room);
            }
            cleanValueCahe(roomId, "dead");
            return RtnJson.toSuccess();
        }
    }

    /**
     * 熊咆哮
     *
     * @return
     */
    private Room roar(Room room) {
        if (room.getXiongNum() != 0) {
            ArrayList<User> survivor = new ArrayList<>();
            int xiongIndexOf = 0;
            int first = 0;
            int second = 0;
            boolean flag = false;
            for (User user : room.getUsers()) {
                if (user.getHp() != 0) {
                    survivor.add(user);
                    if (user.getRole().getRoleId() == 10) {
                        xiongIndexOf = survivor.size() - 1;
                    }
                }
            }
//            幸存者中判断是否有狼
            if (xiongIndexOf == (survivor.size() - 1)) {
                first = survivor.size() - 2;
                second = 0;
            } else if (xiongIndexOf == 0) {
                first = survivor.size() - 1;
                second = 1;
            } else {
                first = xiongIndexOf - 1;
                second = xiongIndexOf + 1;
            }
            if (survivor.get(first).getRole().getRoleId() == 2 || survivor.get(second).getRole().getRoleId() == 2) {
                flag = true;
            }
            if (flag) {
                room.setRoomStatus(ProcessConstant.XIONG_PAO_XIAO.getStatus());
                return updateRoomStatus(room);
            }
        }
        room.setRoomStatus(ProcessConstant.XIONG_MEI_YOU_PAO_XIAO.getStatus());
        return updateRoomStatus(room);
    }

    /**
     * 清空value缓存
     */
    private void cleanValueCahe(int roomId, String status) {
        redisTemplate.delete(roomId + status);
    }

    /**
     * 狼人使用技能
     *
     * @param roomId
     * @param seatNum
     * @param target
     * @param room
     * @return
     */
    private RtnJson langRenSkill(int roomId, int seatNum, int target, Room room) {
        if (room.getRoomStatus() != ProcessConstant.HEI_YE.getStatus()) {
            return RtnJson.toFail(CommonStatusCode.E00010009);
        }
        setVoteCache(roomId, "langRen", seatNum, target);
        Map langRen = getVoteCache(roomId, "langRen");
        if (langRen.size() == room.getLangRenNum()) {
            LinkedHashMap<Integer, Integer> sortMap = countVote(roomId, langRen);
            Integer first = sortMap.entrySet().iterator().next().getKey();
            if (first != 0) {
                try {
                    MyWebSocket.sendInfo("2");
                    MyWebSocket.sendInfo("2");
                } catch (IOException e) {
                    e.printStackTrace();
                }
                log.error("狼人杀死的是:" + first + "号");
                sleepTime(1000);
                cleanVoteCache(roomId, "langRen");
                setValueCache(roomId, "dead", first);
                setVoteCache(roomId, "langRen", 0, first);
                try {
                    MyWebSocket.sendInfo("2");
                    MyWebSocket.sendInfo("2");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            sleepTime(3000);
            room.setRoomStatus(ProcessConstant.LANG_REN_BI_YAN.getStatus());
            room = updateRoomStatus(room);
            if (room.isShouWeiFlag()) {
                sleepTime(2000);
                room.setRoomStatus(ProcessConstant.SHOU_WEI_ZHENG_YAN.getStatus());
                room = updateRoomStatus(room);
                if (room.getShouWeiNum() == 0) {
                    sleepTime((int) (Math.random() * 5 + 8) * 1000);
                    room.setRoomStatus(ProcessConstant.SHOU_WEI_BI_YAN.getStatus());
                    room = updateRoomStatus(room);
                    sleepTime(2000);
                    room.setRoomStatus(ProcessConstant.YU_YAN_JIA_ZHENG_YAN.getStatus());
                    room = updateRoomStatus(room);
                    if (room.getYuYanJiaNum() == 0) {
                        sleepTime((int) (Math.random() * 5 + 8) * 1000);
                        room.setRoomStatus(ProcessConstant.YU_YAN_JIA_BI_YAN.getStatus());
                        room = updateRoomStatus(room);
                        sleepTime(2000);
                        room.setRoomStatus(ProcessConstant.NV_WU_ZHENG_YAN.getStatus());
                        room = updateRoomStatus(room);
                        if (room.getNvWuNum() == 0) {
                            sleepTime((int) (Math.random() * 5 + 8) * 1000);
                            room.setRoomStatus(ProcessConstant.NV_WU_BI_YAN.getStatus());
                            room = updateRoomStatus(room);
                            sleepTime(2000);
                            ArrayList<Integer> deadList = new ArrayList<>();
                            Integer shouWei = getValueCache(roomId, "shouWei");
                            Integer langRenTarg = getValueCache(roomId, "dead");
                            if (langRenTarg != 0) {
                                if (langRenTarg != shouWei) {
                                    room = setDead(room, langRenTarg);
                                    deadList.add(langRenTarg);
                                }
                            }
                            return setDawnStatus(roomId, room, deadList);
                        }
                    }
                }
            } else {
                sleepTime(2000);
                room.setRoomStatus(ProcessConstant.YU_YAN_JIA_ZHENG_YAN.getStatus());
                room = updateRoomStatus(room);
                if (room.getYuYanJiaNum() == 0) {
                    sleepTime((int) (Math.random() * 5 + 8) * 1000);
                    room.setRoomStatus(ProcessConstant.YU_YAN_JIA_BI_YAN.getStatus());
                    room = updateRoomStatus(room);
                    sleepTime(2000);
                    room.setRoomStatus(ProcessConstant.NV_WU_ZHENG_YAN.getStatus());
                    room = updateRoomStatus(room);
                    if (room.getNvWuNum() == 0) {
                        sleepTime((int) (Math.random() * 5 + 8) * 1000);
                        room.setRoomStatus(ProcessConstant.NV_WU_BI_YAN.getStatus());
                        room = updateRoomStatus(room);
                        sleepTime(2000);
                        ArrayList<Integer> deadList = new ArrayList<>();
                        Integer shouWei = getValueCache(roomId, "shouWei");
                        Integer langRenTarg = getValueCache(roomId, "dead");
                        if (langRenTarg != 0) {
                            if (langRenTarg != shouWei) {
                                room = setDead(room, langRenTarg);
                                deadList.add(langRenTarg);
                            }
                        }
                        return setDawnStatus(roomId, room, deadList);
                    }
                }
            }
            cleanVoteCache(roomId, "langRen");
        }
        try {
            MyWebSocket.sendInfo("2");
            MyWebSocket.sendInfo("2");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return RtnJson.toSuccess();
    }

    private void sleepTime(int i) {
        try {
            Thread.sleep(i);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 设置value缓存
     *
     * @param roomId
     * @param status
     * @param deadNum
     */
    private void setValueCache(int roomId, String status, int num) {
        redisTemplate.opsForValue().set(roomId + status, num);
    }

    /**
     * 获取value缓存
     *
     * @param deadNum
     * @param roomId
     * @param status
     * @return
     */
    private int getValueCache(int roomId, String status) {
        Object o = redisTemplate.opsForValue().get(roomId + status);
        if (null != o) {
            return (int) o;
        }
        return 0;
    }

    /**
     * 狼人查看队友技能
     *
     * @param roomId
     * @return
     */
    public RtnJson langRenFindSkill(int roomId) {
        Map<Integer, Integer> langRen = getVoteCache(roomId, "langRen");
        ArrayList<LangRenSkill> list = new ArrayList<>();
        for (Integer i : langRen.keySet()) {
            LangRenSkill langRenSkill = new LangRenSkill();
            langRenSkill.setSeatNum(i);
            langRenSkill.setTarget(langRen.get(i));
            list.add(langRenSkill);
        }
        return RtnJson.toSuccess(list);
    }

    /**
     * 女巫查看已死亡人员
     *
     * @param roomId
     * @return
     */
    public RtnJson nvWuViewDead(int roomId) {
        Room room = roomInfo(roomId);
        Integer dead = getValueCache(roomId, "dead");
        for (User user : room.getUsers()) {
            if (user.getRole().getRoleId() == RoleConstant.NV_WU.getRoleId() &&
                    user.getRole().getSkill().get(0).getNum() == 0) {
                dead = 0;
            }
        }
        return RtnJson.toSuccess(dead);
    }

    /**
     * 法官设置座位死亡/复活
     *
     * @param roomId
     * @param homeownerId
     * @param seatNum
     * @param hp
     * @return
     */
    public RtnJson setDead(int roomId, String homeownerId, int seatNum, int hp) {
        Room room = roomInfo(roomId);
        if (!room.getHomeownerId().equals(homeownerId)) {
            return RtnJson.toFail(CommonStatusCode.E00010006);
        }
        if (hp == 0) {
            room = setDead(room, seatNum);
        } else {
            setRevive(room, seatNum);
        }
        return RtnJson.toSuccess();
    }

    /**
     * 使玩家复活
     *
     * @param room
     * @param seatNum
     */
    private void setRevive(Room room, int seatNum) {
        List<User> users = room.getUsers();
        for (User user : users) {
            if (user.getSeatNum() == seatNum) {
                user.setHp(1);
                updateRoomStatus(room);
            }
        }
    }

    /**
     * 更改房间状态
     *
     * @param roomId
     * @param status
     * @return
     */
    public RtnJson setStatus(int roomId, int status) {
        Room room = roomInfo(roomId);
        room.setRoomStatus(status);
        updateRoomStatus(room);
        return RtnJson.toSuccess();
    }
}
